package concurrent;


import java.util.HashSet;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;


/**
 * Kontroll bekommt die haelfte der Maschen des Splitter-Threads (wenn dies mehr als 2 waren) und bearbeitet diese
 * @author Patrick Bender, Lukas Subel
 */
public class Kontroll implements Runnable {

	// All diese Variablen sind nebenlauefig benutzte, von der Oberklasse gelieferte Referenzen
	private HashSet<Masche> maschen;
	private HashSet<Node> marked;
	private HashSet<Masche> listeAllerMaschen;
	private CountUpAndDownLatch cutLatch;
	private CountDownLatch unterLatch;
	private ExecutorService executor;
	private ExecutorService hilfsExecutor;
	private CountDownLatch lockLatch;
	
	
	/**
	 * Konstruktor; Uebergibt nebenlaeufig benutzte Variablen an die Klasse
	 * @param maschen enthaelt die Liste aller zu bearbeitenden Maschen
	 * @param marked enthaelt alle markierten Knoten
	 * @param listeAllerMaschen enthaelt die Liste aller Maschen
	 * @param cutLatch zaehlt aktuell Laufende Splitter-Threads
	 * @param unterLatch gibt an ob der Kontroll-Thread fertig mit bearbeiten seiner zu bearbeitenden Maschen ist
	 * @param executor wird benutzt um neue Splitter-Threads zu starten
	 * @param hilfsExecutor wird benutzt um neue Kontroll-Threads zu starten
	 * @param lockLatch wird benutzt um dem Eltern-Splitter-Thread mitzuteilen das alle Locks genommen wurden
	 */
	public Kontroll (HashSet<Masche> maschen, HashSet<Node> marked, HashSet<Masche> listeAllerMaschen, CountUpAndDownLatch cutLatch, CountDownLatch unterLatch, ExecutorService executor, ExecutorService hilfsExecutor, CountDownLatch lockLatch) {
		this.maschen = maschen;
		this.marked = marked;
		this.listeAllerMaschen = listeAllerMaschen;
		this.cutLatch = cutLatch;
		this.unterLatch = unterLatch;
		this.executor = executor;
		this.lockLatch = lockLatch;
		this.hilfsExecutor = hilfsExecutor;
	}
	
	@Override
	public void run() {
		try {
			//Locke alle maschen die du benutzen willst
			for (Masche actMasche : maschen) {
				actMasche.lock();
			}
			//Und sag dann bescheid das du fertig mit locken bist damit im Splitter-Thread die Liste der Maschen wieder freigegeben werden kann
			lockLatch.countDown();
			
			//Bearbeite die Maschen
			Splitter.bearbeiteMaschen(maschen, marked, executor, hilfsExecutor, listeAllerMaschen, cutLatch);
			
			//Benachrichtige den Splitter-Thread das du fertig mit arbeiten bist
			unterLatch.countDown();
		}
		catch (Exception e) {
			// Im Fehlerfall den Fehler ausgeben und Terminieren
			e.printStackTrace();
			System.exit(-1);
		}
	}

}
